package com.cmc.cloud.cmclink.doc.service.impl.multimodaltransport;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.cmc.cloud.cmclink.doc.api.document.emums.ConfirmStatusEnum;
import com.cmc.cloud.cmclink.doc.api.document.emums.ExImTypeEnum;
import com.cmc.cloud.cmclink.doc.constants.errorconstant.BlnoErrorCodeConstants;
import com.cmc.cloud.cmclink.doc.constants.errorconstant.BlnoVslvoyErrorCodeConstants;
import com.cmc.cloud.cmclink.doc.constants.errorconstant.ManifestErrorCodeConstants;
import com.cmc.cloud.cmclink.doc.constants.errorconstant.TblisustampFilesErrorCodeConstants;
import com.cmc.cloud.cmclink.doc.entity.BlnoDO;
import com.cmc.cloud.cmclink.doc.entity.BlnoVslvoyDO;
import com.cmc.cloud.cmclink.doc.entity.ManifestDO;
import com.cmc.cloud.cmclink.doc.entity.ManifestVslvoyDO;
import com.cmc.cloud.cmclink.doc.mapper.BlnoVslvoyMapper;
import com.cmc.cloud.cmclink.doc.mapper.ManifestMapper;
import com.cmc.cloud.cmclink.doc.mapper.ManifestVslvoyMapper;
import com.cmc.cloud.cmclink.doc.rpcservice.CustomerRpcService;
import com.cmc.cloud.cmclink.doc.service.manifest.ManifestService;
import com.cmc.cloud.cmclink.doc.service.multimodaltransport.BlnoLinerPreService;
import com.cmc.cloud.cmclink.doc.service.si.BlnoService;
import com.cmc.cloud.cmclink.doc.util.CostChargeUtil;
import com.cmc.cloud.cmclink.doc.util.I18nsUtil;
import com.cmc.cloud.cmclink.doc.util.VslvoyUtil;
import com.cmc.cloud.cmclink.doc.vo.multimodaltransport.blnolinerpre.*;
import com.cmc.cloud.cmclink.svl.api.base.resp.VesselVoyRespDTO;
import com.cmes.framework.common.exception.util.ServiceExceptionUtil;
import com.cmes.framework.common.pojo.PageResult;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;

import javax.annotation.Resource;
import javax.validation.Valid;
import java.util.*;

/**
 * 提单前程支线船名航次维护 接口
 *
 * @author 申天青
 **/
@Service
@Validated
@Slf4j
public class BlnoLinerPreServiceImpl implements BlnoLinerPreService {
    @Resource
    private BlnoVslvoyMapper blnoVslvoyMapper;
    @Resource
    private VslvoyUtil vslvoyUtil;
    @Resource
    private BlnoService blnoService;
    @Resource
    private ManifestService manifestService ;
    @Resource
    private ManifestVslvoyMapper manifestVslvoyMapper;
    @Resource
    private I18nsUtil i18nsUtil;
    @Resource
    private CustomerRpcService nameTransferService;
    @Resource
    private CostChargeUtil costChargeUtil;
    @Resource
    private ManifestMapper manifestMapper;
    @Override
    public List<UpdateBlnoLinerPreCheckMsgReqVO> setLinerPre(UpdateBlnoLinerPreAllReqVO reqVo, ExImTypeEnum exImType) {

        if(reqVo.getBlnoIds()!=null && !reqVo.getBlnoIds().stream().allMatch(Objects::isNull)){
            return setLinerPreBlno(reqVo, exImType);
        }
        if(reqVo.getManifestIds()!=null && !reqVo.getManifestIds().stream().allMatch(Objects::isNull)){
            return setLinerPreManifest(reqVo, exImType);
        }
        return new ArrayList<>();
    }
    public List<UpdateBlnoLinerPreCheckMsgReqVO> setLinerPreBlno(UpdateBlnoLinerPreAllReqVO reqVo, ExImTypeEnum exImType) {
        List<BlnoDO> blnoList = blnoService.getBlnoList(reqVo.getBlnoIds());
        Locale currentLocale = LocaleContextHolder.getLocale();
        List<UpdateBlnoLinerPreCheckMsgReqVO> msgReqVos = new ArrayList<>();
        List<BlnoVslvoyDO> blnoVslvoyDosUpdate = new ArrayList<>();
        for (BlnoDO blnoDO : blnoList) {
            //3. 提单已锁定不允许更改（提单锁）
            if (Objects.equals(true, blnoDO.getBlLockFlag())) {
//                throw ServiceExceptionUtil.exception(BlnoErrorCodeConstants.SI_LOCK_ERROR);
            }else{
                //4. Confirm 时校验录入的驳船卸货港是否与海船装港一致，不一致时提醒。
                BlnoVslvoyDO blnoVslvoyDoPre = blnoVslvoyMapper.selectOne(new LambdaQueryWrapper<BlnoVslvoyDO>()
                        .eq(BlnoVslvoyDO::getBlnoId, blnoDO.getId())
                        .eq(exImType.isIm(), BlnoVslvoyDO::getVoyageIm, reqVo.getPreVoyageCodeOld())
                        .eq(exImType.isIm(), BlnoVslvoyDO::getPolCode, reqVo.getTsPort())
                        .eq(exImType.isEx(), BlnoVslvoyDO::getVoyageEx, reqVo.getPreVoyageCodeOld())
                        .eq(exImType.isEx(), BlnoVslvoyDO::getPodCode, reqVo.getTsPort())
                        .eq( BlnoVslvoyDO::getVesselCode, reqVo.getPreVesselCodeOld())
                        .last("limit 1")
                );
                if(blnoVslvoyDoPre==null){
                    throw ServiceExceptionUtil.exception(BlnoVslvoyErrorCodeConstants.BLNO_VSLVOY_NOT_EXISTS);
                }else{
                    //对应的海船
                    BlnoVslvoyDO blnoVslvoyDoLiner = blnoVslvoyMapper.selectOne(new LambdaQueryWrapper<BlnoVslvoyDO>()
                            .eq(BlnoVslvoyDO::getBlnoId, blnoDO.getId())
                            .eq(exImType.isIm(), BlnoVslvoyDO::getVoyageIm, reqVo.getLinerVoyageOld())
                            .eq(exImType.isIm(), BlnoVslvoyDO::getPodCode, reqVo.getTsPort())
                            .eq(exImType.isEx(), BlnoVslvoyDO::getVoyageEx, reqVo.getLinerVoyageOld())
                            .eq(exImType.isEx(), BlnoVslvoyDO::getPolCode, reqVo.getTsPort())
                            .eq( BlnoVslvoyDO::getVesselCode, reqVo.getLinerVesselCodeOld())
                            .last("limit 1")
                    );
                    if(blnoVslvoyDoLiner!=null){
                        blnoVslvoyDoPre.setVesselCode(reqVo.getPreVesselCodeNew());
                        blnoVslvoyDoPre.setVesselOperator(reqVo.getPrePartnerCodeNew());
                        if(exImType.isEx()){
                            blnoVslvoyDoPre.setVoyageEx(reqVo.getPreVoyageCodeNew());
                        }
                        if(exImType.isIm()){
                            blnoVslvoyDoPre.setVoyageIm(reqVo.getPreVoyageCodeNew());
                        }
                        blnoVslvoyDosUpdate.add(blnoVslvoyDoPre);
                    }else{
                        throw ServiceExceptionUtil.exception(BlnoVslvoyErrorCodeConstants.BLNO_VSLVOY_NOT_EXISTS);
                    }
                }
            }

        }
        if(!blnoVslvoyDosUpdate.isEmpty()){
            blnoVslvoyMapper.updateBatch(blnoVslvoyDosUpdate);
        }
        return msgReqVos;
    }
    public List<UpdateBlnoLinerPreCheckMsgReqVO> setLinerPreManifest(UpdateBlnoLinerPreAllReqVO reqVo, ExImTypeEnum exImType) {
        List<ManifestDO> manifestList = manifestService.getManifestList(reqVo.getManifestIds());
        Locale currentLocale = LocaleContextHolder.getLocale();
        List<UpdateBlnoLinerPreCheckMsgReqVO> msgReqVos = new ArrayList<>();
        List<ManifestDO> manifestUpdate = new ArrayList<>();
        for (ManifestDO manifestDO : manifestList) {
            //舱单已确认状态不允许更新。
            if (Objects.equals(ConfirmStatusEnum.Y.getValue(), manifestDO.getConfirmStatus())) {
//                throw ServiceExceptionUtil.exception(BlnoErrorCodeConstants.SI_LOCK_ERROR);
            }else{
                manifestDO.setPreVessel(reqVo.getPreVesselCodeNew());
                manifestDO.setPreVoyage(reqVo.getPreVoyageCodeNew());
                manifestUpdate.add(manifestDO);
            }

        }
        if(!manifestUpdate.isEmpty()){
            manifestMapper.updateBatch(manifestUpdate);
        }
        return msgReqVos;
    }

    @Override
    public List<UpdateBlnoLinerPreCheckMsgReqVO> checkLinerPre(@Valid CheckBlnoLinerPreAllReqVO reqVo, ExImTypeEnum exImType) {

        if(reqVo.getBlnoIds()!=null && !reqVo.getBlnoIds().stream().allMatch(Objects::isNull)){
            return checkLinerPreBlno(reqVo, exImType);
        }
        if(reqVo.getManifestIds()!=null && !reqVo.getManifestIds().stream().allMatch(Objects::isNull)){
            return checkLinerPreManifest(reqVo, exImType);
        }
        return new ArrayList<>();
    }
    public List<UpdateBlnoLinerPreCheckMsgReqVO> checkLinerPreBlno(@Valid CheckBlnoLinerPreAllReqVO reqVo, ExImTypeEnum exImType) {

        List<BlnoDO> blnoList = blnoService.getBlnoList(reqVo.getBlnoIds());
        Locale currentLocale = LocaleContextHolder.getLocale();
        List<UpdateBlnoLinerPreCheckMsgReqVO> msgReqVos = new ArrayList<>();
        for (BlnoDO blnoDO : blnoList) {
            //3. 提单已锁定不允许更改（提单锁）
            if (Objects.equals(true, blnoDO.getBlLockFlag())) {
                throw ServiceExceptionUtil.exception(BlnoErrorCodeConstants.SI_LOCK_ERROR);
            }else{
                //4. Confirm 时校验录入的驳船卸货港是否与海船装港一致，不一致时提醒。
                BlnoVslvoyDO blnoVslvoyDoPre = blnoVslvoyMapper.selectOne(new LambdaQueryWrapper<BlnoVslvoyDO>()
                        .eq(BlnoVslvoyDO::getBlnoId, blnoDO.getId())
                        .eq(exImType.isIm(), BlnoVslvoyDO::getVoyageIm, reqVo.getPreVoyageCodeOld())
                        .eq(exImType.isIm(), BlnoVslvoyDO::getPolCode, reqVo.getTsPort())
                        .eq(exImType.isEx(), BlnoVslvoyDO::getVoyageEx, reqVo.getPreVoyageCodeOld())
                        .eq(exImType.isEx(), BlnoVslvoyDO::getPodCode, reqVo.getTsPort())
                        .eq( BlnoVslvoyDO::getVesselCode, reqVo.getPreVesselCodeOld())
                        .last("limit 1")
                );
                if(blnoVslvoyDoPre==null){
                    throw ServiceExceptionUtil.exception(BlnoVslvoyErrorCodeConstants.BLNO_VSLVOY_NOT_EXISTS);
//                    msgReqVos.add(new UpdateBlnoLinerPreCheckMsgReqVO(blnoDO.getBlNo(),"", i18nsUtil.getMessage(BlnoVslvoyErrorCodeConstants.BLNO_VSLVOY_NOT_EXISTS.getCode(), currentLocale)));
                }else{
                    //对应的海船
                    BlnoVslvoyDO blnoVslvoyDoLiner = blnoVslvoyMapper.selectOne(new LambdaQueryWrapper<BlnoVslvoyDO>()
                            .eq(BlnoVslvoyDO::getBlnoId, blnoDO.getId())
                            .eq(exImType.isIm(), BlnoVslvoyDO::getVoyageIm, reqVo.getLinerVoyageOld())
                            .eq(exImType.isIm(), BlnoVslvoyDO::getPodCode, reqVo.getTsPort())
                            .eq(exImType.isEx(), BlnoVslvoyDO::getVoyageEx, reqVo.getLinerVoyageOld())
                            .eq(exImType.isEx(), BlnoVslvoyDO::getPolCode, reqVo.getTsPort())
                            .eq( BlnoVslvoyDO::getVesselCode, reqVo.getLinerVesselCodeOld())
                            .last("limit 1")
                    );
                    if(blnoVslvoyDoLiner!=null){
                        //校验原驳船航次是否为“TBA”或空值，非TBA且非空值时做出提示：”提单已绑定驳船XXX（原驳船船名航次），是否重新绑定？
                        String preVessel = blnoVslvoyDoPre.getVesselCode();
                        String preVoyage = exImType.isIm()?blnoVslvoyDoPre.getVoyageIm():blnoVslvoyDoPre.getVoyageEx();
                        if(!StringUtils.isEmpty(preVoyage)){
                            if(!"TBA".equals(preVoyage)){
                                msgReqVos.add(new UpdateBlnoLinerPreCheckMsgReqVO(blnoDO.getBlNo(),"", i18nsUtil.getMessage(BlnoErrorCodeConstants.BLNO_PRE_VOYAGE_NOT_EMPTY.getCode(), currentLocale)+preVoyage+"/"+preVessel));
                            }
                        }
                    }else{
                        throw ServiceExceptionUtil.exception(BlnoVslvoyErrorCodeConstants.BLNO_VSLVOY_NOT_EXISTS);
//                        msgReqVos.add(new UpdateBlnoLinerPreCheckMsgReqVO(blnoDO.getBlNo(),"", i18nsUtil.getMessage(BlnoVslvoyErrorCodeConstants.BLNO_VSLVOY_NOT_EXISTS.getCode(), currentLocale)));
                    }
                }
            }

        }
        return msgReqVos;
    }
    public List<UpdateBlnoLinerPreCheckMsgReqVO> checkLinerPreManifest(@Valid CheckBlnoLinerPreAllReqVO reqVo, ExImTypeEnum exImType) {

        List<ManifestDO> manifestList = manifestService.getManifestList(reqVo.getManifestIds());
        Locale currentLocale = LocaleContextHolder.getLocale();
        List<UpdateBlnoLinerPreCheckMsgReqVO> msgReqVos = new ArrayList<>();
        for (ManifestDO manifestDO : manifestList) {
            //舱单已确认状态不允许更新。
            if (Objects.equals(ConfirmStatusEnum.Y.getValue(), manifestDO.getConfirmStatus())) {
                throw ServiceExceptionUtil.exception(ManifestErrorCodeConstants.MANIFEST_CONFIRMS_ERROR);
            }else{
                //校验原驳船航次是否为“TBA”或空值，非TBA且非空值时做出提示：”提单已绑定驳船XXX（原驳船船名航次），是否重新绑定？
                String preVessel = manifestDO.getPreVessel();
                String preVoyage = manifestDO.getPreVoyage();
                if( !StringUtils.isEmpty(preVoyage)){
                    if(!"TBA".equals(preVoyage)){
                        msgReqVos.add(new UpdateBlnoLinerPreCheckMsgReqVO("",manifestDO.getManifestNo(), i18nsUtil.getMessage(BlnoErrorCodeConstants.MANIFEST_PRE_VOYAGE_NOT_EMPTY.getCode(), currentLocale)+preVoyage+"/"+preVessel));
                    }
                }
            }

        }
        return msgReqVos;
    }

    @Override
    public PageResult<BlnoLinerPreRespVO> getBlnoLinerPrePage(BlnoLinerPrePageReqVO pageVo, ExImTypeEnum exImType) {

        IPage<BlnoLinerPreRespVO> page = Page.of(pageVo.getPageNo(), pageVo.getPageSize());
        IPage<BlnoLinerPreRespVO> blnoLinerPrePage = new Page<>();
        if (exImType.isEx()) {
            if(pageVo.getFromManifest()){
                //已跟产品确认，只用blNo字段，在最后使用的时候，如果勾选了从舱单查询，当作舱单号过滤舱单字段
                pageVo.setManifestNo(pageVo.getBlNo());
                blnoLinerPrePage = blnoVslvoyMapper.getBlnoLinerPrePageExManifestEx(page, pageVo);
            }else{
                blnoLinerPrePage = blnoVslvoyMapper.getBlnoLinerPrePageEx(page, pageVo);
            }
        }else{
            if(pageVo.getFromManifest()){
                //进口没有舱单查询
//                return new PageResult<>(new ArrayList<>(), 0L);
                throw ServiceExceptionUtil.exception(TblisustampFilesErrorCodeConstants.ILLEGAL_STATUS);
            }else{
                blnoLinerPrePage = blnoVslvoyMapper.getBlnoLinerPrePageIm(page, pageVo);
            }
        }

        //todo 填充合作方名称
        nameTransferService.fillCompanyNameByPartnerCodeFunctionally(
                blnoLinerPrePage.getRecords(),
                // 提取bkpCode的函数
                BlnoLinerPreRespVO::getVesselOperator,
                // 设置本地名称的函数
                BlnoLinerPreRespVO::setPreAgentNameLocal,
                // 设置英文名称的函数
                BlnoLinerPreRespVO::setPreAgentNameEn
        );
        //todo 批量查询
        String tsPort = pageVo.getTsPort();
        for (BlnoLinerPreRespVO record : blnoLinerPrePage.getRecords()) {
            if(exImType.isIm()){
                VesselVoyRespDTO vesselVoyRespDto = vslvoyUtil.getVesselVoyRespDTO(record.getPrePolCode(), record.getPreVoyageCode(), record.getPreVesselCode());
                if (vesselVoyRespDto !=null) {
                    record.setPreEta(vesselVoyRespDto.getEta());
                    record.setPreAtd(vesselVoyRespDto.getAtd());
                }
                VesselVoyRespDTO vesselVoyRespDtoLiner = vslvoyUtil.getVesselVoyRespDTO(record.getLinePodCode(), record.getLineVoyageCode(), record.getLineVesselCode());
                if (vesselVoyRespDtoLiner !=null) {
                    record.setLineEtd(vesselVoyRespDtoLiner.getEtd());
                }
                record.setPrePolTerminal(vslvoyUtil.getVoyPortTerminal(record.getPrePolCode(), record.getPreVoyageCode(), record.getPreVesselCode()));
                record.setPrePodTerminal(vslvoyUtil.getVoyPortTerminal(record.getPrePodCode(), record.getPreVoyageCode(), record.getPreVesselCode()));

                record.setLinePolTerminal(vslvoyUtil.getVoyPortTerminal(record.getLinePolCode(), record.getLineVoyageCode(), record.getLineVesselCode()));
                record.setLinePodTerminal(vslvoyUtil.getVoyPortTerminal(record.getLinePodCode(), record.getLineVoyageCode(), record.getLineVesselCode()));
            }
            if(exImType.isEx()){
                VesselVoyRespDTO vesselVoyRespDto = vslvoyUtil.getVesselVoyRespDTO(record.getPrePodCode(), record.getPreVoyageCode(), record.getPreVesselCode());
                if (vesselVoyRespDto !=null) {
                    record.setPreEta(vesselVoyRespDto.getEta());
                    record.setPreAtd(vesselVoyRespDto.getAtd());
                }
                VesselVoyRespDTO vesselVoyRespDtoLiner = vslvoyUtil.getVesselVoyRespDTO(record.getLinePolCode(), record.getLineVoyageCode(), record.getLineVesselCode());
                if (vesselVoyRespDtoLiner !=null) {
                    record.setLineEtd(vesselVoyRespDtoLiner.getEtd());
                }
                record.setPrePolTerminal(vslvoyUtil.getVoyPortTerminal(record.getPrePolCode(), record.getPreVoyageCode(), record.getPreVesselCode()));
                record.setPrePodTerminal(vslvoyUtil.getVoyPortTerminal(record.getPrePodCode(), record.getPreVoyageCode(), record.getPreVesselCode()));

                record.setLinePolTerminal(vslvoyUtil.getVoyPortTerminal(record.getLinePolCode(), record.getLineVoyageCode(), record.getLineVesselCode()));
                record.setLinePodTerminal(vslvoyUtil.getVoyPortTerminal(record.getLinePodCode(), record.getLineVoyageCode(), record.getLineVesselCode()));
            }
        }
        return new PageResult<>(blnoLinerPrePage.getRecords(), blnoLinerPrePage.getTotal());
    }
}
